
`include "common_header.verilog"

//  *************************************************************************
//  File : descrmbl64.v
//  *************************************************************************
//  This program is controlled by a written license agreement.
//  Unauthorized reproduction or use is expressly prohibited. 
//  Copyright (c) 2008 MorethanIP
//  Muenchner Strasse 199, 85757 Karlsfeld, Germany
//  info@morethanip.com
//  http://www.morethanip.com
//  *************************************************************************
//  Designed by : Daniel Koehler; Thomas Schrobenhauser
//  info@morethanip.com
//  *************************************************************************
//  Description : Self-synchronizing Descrambler for polynom x58+x39+1
//  Version     : $Id: descrmbl64.v,v 1.3 2016/07/13 06:58:13 dk Exp $
//  *************************************************************************

module descrmbl64 (
        reset,
        clk,
        clk_ena,
        scr_bypass,
        sh_in_0,
        din_0,
        sh_out_0,
        dout_0);

input           reset;                  //  active high reset
input           clk;                    //  clock
input           clk_ena;                //  clock enable
input           scr_bypass;             //  bypass descrambling (without changing latency)
input   [1:0]   sh_in_0;                //  Sync header
input   [63:0]  din_0;                  //  Scrambled input data
output  [1:0]   sh_out_0;               //  Sync header	    (registered copy of input)
output  [63:0]  dout_0;                 //  Descrambled output data

reg     [1:0] sh_out_0; 
reg     [63:0] dout_0; 

parameter T1 = 6'b 100111; //  tap 1
parameter T2 = 6'b 111010; //  tap 2
parameter DW = 7'b 1000000; 
wire    [T2 - 1:0] seed; 
reg     [T2 - 1:0] screg_0; //  descrambler history
wire    [DW - 1:0] data_0; //  descrambled input


function [63:0] DESCRMBL64;
input   [63:0] din; 
input   [57:0] screg; 
begin
        // descramble input data
        // ----------------------

        // dat1: for i in 0 to (T1-1) generate
        //     data(i) := screg(T1-1-i) xor screg(T2-1-i) xor din(i);
        // end generate;

           DESCRMBL64[00] = screg[39-1-00] ^ screg[58-1-00] ^ din[00];
           DESCRMBL64[01] = screg[39-1-01] ^ screg[58-1-01] ^ din[01];
           DESCRMBL64[02] = screg[39-1-02] ^ screg[58-1-02] ^ din[02];
           DESCRMBL64[03] = screg[39-1-03] ^ screg[58-1-03] ^ din[03];
           DESCRMBL64[04] = screg[39-1-04] ^ screg[58-1-04] ^ din[04];
           DESCRMBL64[05] = screg[39-1-05] ^ screg[58-1-05] ^ din[05];
           DESCRMBL64[06] = screg[39-1-06] ^ screg[58-1-06] ^ din[06];
           DESCRMBL64[07] = screg[39-1-07] ^ screg[58-1-07] ^ din[07];
           DESCRMBL64[08] = screg[39-1-08] ^ screg[58-1-08] ^ din[08];
           DESCRMBL64[09] = screg[39-1-09] ^ screg[58-1-09] ^ din[09];
           DESCRMBL64[10] = screg[39-1-10] ^ screg[58-1-10] ^ din[10];
           DESCRMBL64[11] = screg[39-1-11] ^ screg[58-1-11] ^ din[11];
           DESCRMBL64[12] = screg[39-1-12] ^ screg[58-1-12] ^ din[12];
           DESCRMBL64[13] = screg[39-1-13] ^ screg[58-1-13] ^ din[13];
           DESCRMBL64[14] = screg[39-1-14] ^ screg[58-1-14] ^ din[14];
           DESCRMBL64[15] = screg[39-1-15] ^ screg[58-1-15] ^ din[15];
           DESCRMBL64[16] = screg[39-1-16] ^ screg[58-1-16] ^ din[16];
           DESCRMBL64[17] = screg[39-1-17] ^ screg[58-1-17] ^ din[17];
           DESCRMBL64[18] = screg[39-1-18] ^ screg[58-1-18] ^ din[18];
           DESCRMBL64[19] = screg[39-1-19] ^ screg[58-1-19] ^ din[19];
           DESCRMBL64[20] = screg[39-1-20] ^ screg[58-1-20] ^ din[20];
           DESCRMBL64[21] = screg[39-1-21] ^ screg[58-1-21] ^ din[21];
           DESCRMBL64[22] = screg[39-1-22] ^ screg[58-1-22] ^ din[22];
           DESCRMBL64[23] = screg[39-1-23] ^ screg[58-1-23] ^ din[23];
           DESCRMBL64[24] = screg[39-1-24] ^ screg[58-1-24] ^ din[24];
           DESCRMBL64[25] = screg[39-1-25] ^ screg[58-1-25] ^ din[25];
           DESCRMBL64[26] = screg[39-1-26] ^ screg[58-1-26] ^ din[26];
           DESCRMBL64[27] = screg[39-1-27] ^ screg[58-1-27] ^ din[27];
           DESCRMBL64[28] = screg[39-1-28] ^ screg[58-1-28] ^ din[28];
           DESCRMBL64[29] = screg[39-1-29] ^ screg[58-1-29] ^ din[29];
           DESCRMBL64[30] = screg[39-1-30] ^ screg[58-1-30] ^ din[30];
           DESCRMBL64[31] = screg[39-1-31] ^ screg[58-1-31] ^ din[31];
           DESCRMBL64[32] = screg[39-1-32] ^ screg[58-1-32] ^ din[32];
           DESCRMBL64[33] = screg[39-1-33] ^ screg[58-1-33] ^ din[33];
           DESCRMBL64[34] = screg[39-1-34] ^ screg[58-1-34] ^ din[34];
           DESCRMBL64[35] = screg[39-1-35] ^ screg[58-1-35] ^ din[35];
           DESCRMBL64[36] = screg[39-1-36] ^ screg[58-1-36] ^ din[36];
           DESCRMBL64[37] = screg[39-1-37] ^ screg[58-1-37] ^ din[37];
           DESCRMBL64[38] = screg[39-1-38] ^ screg[58-1-38] ^ din[38];

        // dat2: for i in T1 to (T2-1) generate
        //     data(i) := din(i-T1) xor screg(T2-1-i) xor din(i);
        // end generate;

           DESCRMBL64[39] = din[39-39] ^ screg[58-1-39] ^ din[39];
           DESCRMBL64[40] = din[40-39] ^ screg[58-1-40] ^ din[40];
           DESCRMBL64[41] = din[41-39] ^ screg[58-1-41] ^ din[41];
           DESCRMBL64[42] = din[42-39] ^ screg[58-1-42] ^ din[42];
           DESCRMBL64[43] = din[43-39] ^ screg[58-1-43] ^ din[43];
           DESCRMBL64[44] = din[44-39] ^ screg[58-1-44] ^ din[44];
           DESCRMBL64[45] = din[45-39] ^ screg[58-1-45] ^ din[45];
           DESCRMBL64[46] = din[46-39] ^ screg[58-1-46] ^ din[46];
           DESCRMBL64[47] = din[47-39] ^ screg[58-1-47] ^ din[47];
           DESCRMBL64[48] = din[48-39] ^ screg[58-1-48] ^ din[48];
           DESCRMBL64[49] = din[49-39] ^ screg[58-1-49] ^ din[49];
           DESCRMBL64[50] = din[50-39] ^ screg[58-1-50] ^ din[50];
           DESCRMBL64[51] = din[51-39] ^ screg[58-1-51] ^ din[51];
           DESCRMBL64[52] = din[52-39] ^ screg[58-1-52] ^ din[52];
           DESCRMBL64[53] = din[53-39] ^ screg[58-1-53] ^ din[53];
           DESCRMBL64[54] = din[54-39] ^ screg[58-1-54] ^ din[54];
           DESCRMBL64[55] = din[55-39] ^ screg[58-1-55] ^ din[55];
           DESCRMBL64[56] = din[56-39] ^ screg[58-1-56] ^ din[56];
           DESCRMBL64[57] = din[57-39] ^ screg[58-1-57] ^ din[57];

        // dat3: for i in T2 to (DW-1) generate
        //     data(i) := din(i-T2) xor din(i-T1) xor din(i);
        // end generate;

           DESCRMBL64[58] = din[58-58] ^ din[58-39] ^ din[58];
           DESCRMBL64[59] = din[59-58] ^ din[59-39] ^ din[59];
           DESCRMBL64[60] = din[60-58] ^ din[60-39] ^ din[60];
           DESCRMBL64[61] = din[61-58] ^ din[61-39] ^ din[61];
           DESCRMBL64[62] = din[62-58] ^ din[62-39] ^ din[62];
           DESCRMBL64[63] = din[63-58] ^ din[63-39] ^ din[63];
end
endfunction

always @(posedge reset or posedge clk)
   begin : process_1
   if (reset == 1'b 1)
      begin
      dout_0 <= {64{1'b 0}};		
      screg_0 <= {(T2){1'b 0}};	
      sh_out_0 <= {2{1'b 0}};	//  Sync header
      end
   else
      begin
      if (clk_ena == 1'b 1)
         begin
         dout_0 <= data_0;	
         screg_0 <= seed;	
         sh_out_0 <= sh_in_0;	
         end
      end
   end

assign data_0 = scr_bypass==1'b 1 ? din_0 : DESCRMBL64(din_0, screg_0); 

//  MSB is shifted in last and ends up at the lowest position in the scrambler
//  ---------------------------

assign seed[57] = din_0[DW - 1 - 57]; 
assign seed[56] = din_0[DW - 1 - 56]; 
assign seed[55] = din_0[DW - 1 - 55]; 
assign seed[54] = din_0[DW - 1 - 54]; 
assign seed[53] = din_0[DW - 1 - 53]; 
assign seed[52] = din_0[DW - 1 - 52]; 
assign seed[51] = din_0[DW - 1 - 51]; 
assign seed[50] = din_0[DW - 1 - 50]; 
assign seed[49] = din_0[DW - 1 - 49]; 
assign seed[48] = din_0[DW - 1 - 48]; 
assign seed[47] = din_0[DW - 1 - 47]; 
assign seed[46] = din_0[DW - 1 - 46]; 
assign seed[45] = din_0[DW - 1 - 45]; 
assign seed[44] = din_0[DW - 1 - 44]; 
assign seed[43] = din_0[DW - 1 - 43]; 
assign seed[42] = din_0[DW - 1 - 42]; 
assign seed[41] = din_0[DW - 1 - 41]; 
assign seed[40] = din_0[DW - 1 - 40]; 
assign seed[39] = din_0[DW - 1 - 39]; 
assign seed[38] = din_0[DW - 1 - 38]; 
assign seed[37] = din_0[DW - 1 - 37]; 
assign seed[36] = din_0[DW - 1 - 36]; 
assign seed[35] = din_0[DW - 1 - 35]; 
assign seed[34] = din_0[DW - 1 - 34]; 
assign seed[33] = din_0[DW - 1 - 33]; 
assign seed[32] = din_0[DW - 1 - 32]; 
assign seed[31] = din_0[DW - 1 - 31]; 
assign seed[30] = din_0[DW - 1 - 30]; 
assign seed[29] = din_0[DW - 1 - 29]; 
assign seed[28] = din_0[DW - 1 - 28]; 
assign seed[27] = din_0[DW - 1 - 27]; 
assign seed[26] = din_0[DW - 1 - 26]; 
assign seed[25] = din_0[DW - 1 - 25]; 
assign seed[24] = din_0[DW - 1 - 24]; 
assign seed[23] = din_0[DW - 1 - 23]; 
assign seed[22] = din_0[DW - 1 - 22]; 
assign seed[21] = din_0[DW - 1 - 21]; 
assign seed[20] = din_0[DW - 1 - 20]; 
assign seed[19] = din_0[DW - 1 - 19]; 
assign seed[18] = din_0[DW - 1 - 18]; 
assign seed[17] = din_0[DW - 1 - 17]; 
assign seed[16] = din_0[DW - 1 - 16]; 
assign seed[15] = din_0[DW - 1 - 15]; 
assign seed[14] = din_0[DW - 1 - 14]; 
assign seed[13] = din_0[DW - 1 - 13]; 
assign seed[12] = din_0[DW - 1 - 12]; 
assign seed[11] = din_0[DW - 1 - 11]; 
assign seed[10] = din_0[DW - 1 - 10]; 
assign seed[9] = din_0[DW - 1 - 9]; 
assign seed[8] = din_0[DW - 1 - 8]; 
assign seed[7] = din_0[DW - 1 - 7]; 
assign seed[6] = din_0[DW - 1 - 6]; 
assign seed[5] = din_0[DW - 1 - 5]; 
assign seed[4] = din_0[DW - 1 - 4]; 
assign seed[3] = din_0[DW - 1 - 3]; 
assign seed[2] = din_0[DW - 1 - 2]; 
assign seed[1] = din_0[DW - 1 - 1]; 
assign seed[0] = din_0[DW - 1 - 0]; 

endmodule // module descrmbl64

